#pragma once
#include "../common/net.hpp"
#include "requestor.hpp"
#include <future>
namespace qiangsir
{
    namespace client
    {
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using AsyncJsonResponse = std::future<Json::Value>;
            using AsyncJsonCallBack = std::function<void(const Json::Value &)>;
            RpcCaller(const Requestor::ptr &requestor) : _requestor(requestor)
            {
            }
            // 同步
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, Json::Value &result)
            {
                // 1.组织请求
                RpcRequest::ptr rpc_req = BaseMessageFactory::create<RpcRequest>();
                rpc_req->setId(UUID::uuid());
                rpc_req->setMethod(method);
                rpc_req->setParams(params);
                rpc_req->setType(MType::REQ_RPC);
                // 2.发送请求
                BaseMessage::ptr resp;
                bool ret = _requestor->send(conn, rpc_req, resp);
                if (ret == false)
                {
                    ELOG("同步rpc请求发送失败");
                    return false;
                }
                // 3.等待响应
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(resp);
                if (!rpc_rsp_msg)
                {
                    ELOG("rpc响应类型向下转换失败");
                    return false;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc请求出错, %s ", errReason(rpc_rsp_msg->rcode()).c_str());
                    return false;
                }
                result = rpc_rsp_msg->result();
                return true;
            }
            // 异步
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, std::future<Json::Value> &result)
            {
                // 1.组织请求
                RpcRequest::ptr rpc_req = BaseMessageFactory::create<RpcRequest>();
                rpc_req->setId(UUID::uuid());
                rpc_req->setMethod(method);
                rpc_req->setParams(params);
                rpc_req->setType(MType::REQ_RPC);

                auto json_promise = std::make_shared<std::promise<Json::Value>>();
                result = json_promise->get_future();
                Requestor::RequestCallBack cb = std::bind(&RpcCaller::callback1, this,
                                                          json_promise, std::placeholders::_1);

                // 2.发送请求
                bool ret = _requestor->send(conn, rpc_req, cb);
                if (ret == false)
                {
                    ELOG("异步请求失败");
                    return false;
                }
                return true;
            }
            // 回调函数
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, const AsyncJsonCallBack &cb)
            {
                // 1.组织请求
                RpcRequest::ptr rpc_req = BaseMessageFactory::create<RpcRequest>();
                rpc_req->setId(UUID::uuid());
                rpc_req->setMethod(method);
                rpc_req->setParams(params);
                rpc_req->setType(MType::REQ_RPC);

                Requestor::RequestCallBack req_cb = std::bind(&RpcCaller::callback2,this,cb,std::placeholders::_1);
                bool ret = _requestor->send(conn, rpc_req, req_cb);
                if (ret == false)
                {
                    ELOG("回调函数请求失败");
                    return false;
                }
                return true;
            }

        private:
            void callback1(std::shared_ptr<std::promise<Json::Value>> result,
                           const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    ELOG("rpc响应类型向下转换失败");
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc异步请求出错, %s ", errReason(rpc_rsp_msg->rcode()).c_str());
                    return;
                }
                result->set_value(rpc_rsp_msg->result());
            }
            void callback2(const AsyncJsonCallBack &cb,
                           const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    ELOG("rpc响应类型向下转换失败");
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc异步请求出错, %s ", errReason(rpc_rsp_msg->rcode()).c_str());
                    return;
                }
                cb(rpc_rsp_msg->result());
            }

        private:
            Requestor::ptr _requestor;
        };
    }
}
